package com.gitee.wsl.mathematics.geometry.api

import com.gitee.wsl.mathematics.coordinate.Coordinate
import com.gitee.wsl.mathematics.geometry.d2.contour.segment.SegmentType

interface CurveSegmentShape<N:Number,V: Coordinate<N, V>>: Shape<N, V> {
    val start:  V
    val control: List<V>
    val end: V

    val corner: Boolean
    /**
     * control points, zero-length iff the segment is linear
     */

    val linear: Boolean get() = control.isEmpty()

    val length: N

    /**
     * Returns the type of the segment.
     */
    val type: SegmentType
        get() {
            return if (linear) {
                SegmentType.LINEAR
            } else {
                if (control.size == 1) {
                    SegmentType.QUADRATIC
                } else {
                    SegmentType.CUBIC
                }
            }
        }

    /**
     * Returns a point on the segment.
     *
     * @param ut unfiltered [t](https://pomax.github.io/bezierinfo/#explanation), will be clamped between 0.0 and 1.0.
     * @return [T] that lies on the [BezierSegment].
     */
    fun position(ut: N): V

    fun derivative(t: N): V

    /** Returns the direction [T] of between the [Segment2D] anchor points. */
    fun direction(): V = (end - start).normalized

    fun direction(t: N): V = derivative(t).normalized

    /**
     * Samples a new [Segment2D] from the current [Segment2D] starting at [t0] and ending at [t1].
     *
     * @param t0 The starting value of [t](https://pomax.github.io/bezierinfo/#explanation) in the range of `0.0` to `1.0`.
     * @param t1 The ending value of *t* in the range of `0.0` to `1.0`.
     */
    fun sub(t0: Double, t1: Double): CurveSegmentShape<N, V>

    /**
     * Splits the path into one or two parts, depending on if the cut was successful.
     *
     * @param t The point at which to split the [Segment2D] at.
     * @return An array of parts, depending on the split point this is one or two entries long.
     */
    fun split(t: Double): Array<out CurveSegmentShape<N, V>>

    val reverse: CurveSegmentShape<N, V>

    /**
     * Estimate [t](https://pomax.github.io/bezierinfo/#explanation) value for a given length
     * @return A value between `0.0` and `1.0`.
     */
    fun tForLength(length: N): N

    fun create(a:V,b:V): CurveSegmentShape<N, V>

    fun signedArea(): N


}

